package se.webbzon.boltzmann.login;

import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Collection;

import se.webbzon.oschi01.hash.MD5;

public abstract class Login {
	
	// The salt used to create the hashword
	private static final String salt = "6S2VcUuXJvQeJ0I";
	
	// The default domain for the login
	private static final String defaultDomain = "www.haffy-entertainment.se";
	
	// The domain, username of this login
	private String domain, username;
	
	// The hashword of this login
	private byte[] hashword;
	
	// The length of the password
	private int passwordLength;
	
	// A collection of all the listeners to this login
	private final Collection<LoginListener> listeners;
	
	/*============================================================
	Constructors
	============================================================*/
	
	public Login() {
		this(defaultDomain);
	}
	
	public Login(String domain) {
		this.domain = domain;
		listeners = new ArrayList<LoginListener>();
	}
	
	/*============================================================
	Public Methods
	============================================================*/
	
	/** Displays the login dialogue. **/
	public abstract void show();
	
	/** Disposes the login dialogue. **/
	public abstract void dispose();
	
	/** Tries to login with the given username and hashword. **/
	public void login() {
		if (username.isEmpty() || hashword == null) {
			for (LoginListener listener : listeners.toArray(new LoginListener[0]))
				listener.loginRejected(this,"Username and/or password is not set!");
		} else try {
			HTTPLoginAccess access = new HTTPLoginAccess(domain,username,hashword);
			for (LoginListener listener : listeners.toArray(new LoginListener[0]))
				listener.loginAccepted(this, access);
		} catch (AccessException e) {
			for (LoginListener listener : listeners.toArray(new LoginListener[0]))
				listener.loginRejected(this,e.getMessage());
		}
	}
	
	/** Sets the username for this login. **/
	public void setUsername(String username) {
		this.username = username.substring(0,1).toUpperCase() + username.substring(1).toLowerCase();
	}
	
	/** Sets the hashword for this login. **/
	public void setHashword(int passwordLength, byte[] hashword) {
		this.hashword = hashword;
		this.passwordLength = passwordLength;
	}
	
	/** Sets the domain for this login. **/
	public void setDomain(String domain) {
		this.domain = domain;
	}
	
	/** Returns the username of this login. **/
	public String getUsername() {
		return username;
	}
	
	/** Returns the hashword of this login. **/
	public byte[] getHashword() {
		return hashword;
	}
	
	/** Returns the domain of this login. **/
	public String getDomain() {
		return domain;
	}
	
	/** Returns the password length of this login. **/
	public int getPasswordLength() {
		return passwordLength;
	}
	
	/** Adds a listener to this login. **/
	public boolean addListener(LoginListener listener) {
		return listeners.add(listener);
	}
	
	/** Removes a listener from this login. **/
	public boolean removeListener(LoginListener listener) {
		return listeners.remove(listener);
	}
	
	/** Clears all the listeners from this login. **/
	public void clearListeners() {
		listeners.clear();
	}
	
	/*============================================================
	Protected Methods
	============================================================*/
	
	/** Cancels this login. **/
	protected final void cancel() {
		for (LoginListener listener : listeners.toArray(new LoginListener[0]))
			listener.loginCanceled(this);
	}
	
	/** Creates a hashword of the provided username and password. **/
	protected static final byte[] createHashword(String username, String password) {
		MD5 md5 = new MD5();
		String usernameTitle = username.substring(0,1).toUpperCase() + username.substring(1).toLowerCase();
		md5.addString(salt + usernameTitle + password, Charset.forName("UTF-8"));
		return md5.sum();
	}

}
